﻿var Global = (function () {
    
    var TIME_OUT_ID;

    function message(text, options) {
        var defaults = {
            duration: 2000,
            callback: null
        }
        var config = $.extend(defaults, options);
        var $html = $("#alertContainer");
        var scrollbarWidth = getScrollbarWidth();

        if ($html.length == 0) {
            $html = $(
                '<div id="alertContainer" class="alert-container">' +
                '    <div class="alert-wrapper">' + text + '</div>' +
                '</div>'
            )
            $("body").append($html);
        } else {
            $("#alertContainer .alert-wrapper").html(text);
        }
        if (document.body.scrollHeight > document.body.clientHeight) {
            $html.css("width", "100%").css("width", function () {
                return $(this).width() - scrollbarWidth;
            });
        }
        setTimeout(function () { $html.addClass("in"); });
        clearTimeout(TIME_OUT_ID);
        TIME_OUT_ID = setTimeout(function () {
            $html.removeClass("in");
            config.callback && config.callback();
        }, config.duration);

        function getScrollbarWidth() { // thx walsh
            var $body = $(document.body);
            var scrollDiv = document.createElement('div')
            scrollDiv.className = 'modal-scrollbar-measure'
            $body.append(scrollDiv);
            var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
            $body[0].removeChild(scrollDiv);
            return scrollbarWidth
        }
    }

    function getNumber(str){
        try {
            return parseInt(/\d+/.exec(str)[0]);
        } catch (e) {
            console.log(e);
            return null;
        }
    }
    
    function bindButtons() {
        $(document).on("click", "[data-toggle-class]", function () {
            var $target = $($(this).data("target") || this);
            $target.toggleClass($(this).data("toggle-class"));
        });
        $(document).on("click", "[data-toggle-text]", function () {
            var $target = $($(this).data("target") || this);
            var defaultText = $target.data("default-text") || $target.text();
            var toggleText = $target.data("toggle-text");
            if (!$target.data("default-text")) $target.data("default-text", defaultText);
            $target.text() === defaultText ? $target.text(toggleText) : $target.text(defaultText);
        });
        $(document).on("click", "[role='select'] .dropdown-menu > li > a", function () {
            var $this = $(this);
            var $button = $this.closest(".dropdown-menu").siblings("[role='selecteditem']");
            $button.data("value", $this.data("value"));
            $button.text($this.text());
        });
    }

    function extendModal(){
        (function () {
            var origin = $.fn.modal.Constructor.prototype.show;
            $.fn.modal.Constructor.prototype.show = function(_relatedTarget){
                var $modal = $(this.$element);
                if ($modal.hasClass("middle")){
                    var $dialog = $modal.find(".modal-dialog");
                    var $content = $modal.find(".modal-content");
                    var rect = getComputedRect($content);
                    var viewHeight = getViewHeight();
                    if (rect.height > viewHeight){
                        $modal.css({ top: 0, overflow: "auto" });
                    }
                    $dialog.css({ height: rect.height });
                }
                origin.call(this, _relatedTarget);
            }
        })();
        (function () {
            $.fn.openModal = function (options) {
                var defaults = function () {
                    return {
                        title: "&nbsp;",
                        panel: null,
                        confirm: null
                    }
                }
                var config = $.extend(defaults(), options);
                var $modal = $(this);
                var $btnConfirm = $modal.find("[data-action='confirm']");
                $modal.find(".modal-title").html(config.title);
                $btnConfirm.off("click");
                $btnConfirm.click(config.confirm);
                $(config.panel).removeClass("hidden").siblings().addClass("hidden");
                $modal.modal();
            };
        })();
    }

    function getViewHeight(){
        return document.body.clientHeight > 0 ? document.body.clientHeight : document.documentElement.clientHeight;
    }

    function getComputedRect(element, selector){
        var rect = {};
        var targetElement = selector ? $(element).find(selector)[0] : $(element)[0];
        if (targetElement){
            renderHiddenElement(element, function(){
                if (targetElement.getBoundingClientRect){
                    rect = targetElement.getBoundingClientRect();
                } else {
                    rect = {
                        width: $(targetElement).width(),
                        height: $(targetElement).height(),
                        top: targetElement.offsetTop,
                        left: targetElement.offsetLeft
                    };
                    rect.right = rect.left + rect.width;
                    rect.bottom = rect.top + rect.height;
                }
            });
        }
        return rect;
    }

    function renderHiddenElement(element, callback){
        var $element = $(element);
        var hiddenParents = getHiddenParents($element);
        hiddenParents.push($element);
        hiddenParents.forEach(function(item, index, obj){
            $(item).css({
                "visibility": "hidden",
                "position": "absolute",
                "display": "block"
            });
        });
        callback && callback.call($element[0]);
        hiddenParents.forEach(function(item, index, obj){
            $(item).css({
                "visibility": "",
                "position": "",
                "display": ""
            });
        });
    }

    function getHiddenParents(element){
        var hiddenParents = [];
        var parents = $(element).parents();
        for (var i=0; i<parents.length; i++){
            if (parents[i].tagName.toLowerCase() == "body") break;
            if ($(parents[i]).css("display") == "none"){
                hiddenParents.push(parents[i]);
            }
        }
        return hiddenParents;
    }

    function buildString(char, count) {
        if (!count) count = 0;
        var result = "";
        for (var i = 0; i < count; i++) {
            result += char.toString();
        }
        return result;
    }

    function padLeftStr(str, char, count) {
        return buildString(char, count) + str.toString();
    }

    function padRightStr(str, char, count) {
        return str.toString() + buildString(char, count);
    }

    function padLeftString(str, char, length) {
        return buildString(char, length - str.toString().length) + str;
    }

    function padRightString(str, char, length) {
        return str + buildString(char, length - str.toString().length);
    }

    function backToTop(selector, options) {
        function DEFAULTS() {
            return {
                shownScrollTop: 0,
                scrollTarget: window,
                container: ".right-side"
            }
        }
        var config = $.extend(DEFAULTS(), options);
        var $control = $(selector).click(function () {
            $("html, body").animate({ scrollTop: 0 }, 400);
        })
        $(config.container).css({
            top: options.top,
            left: options.left,
            right: options.right,
            bottom: options.bottom
        });
        function scrollHandler() {
            var scrollTop = $(config.scrollTarget).scrollTop();
            if (scrollTop > config.shownScrollTop){
                $control.show();
            } else {
                $control.hide();
            }
        }
        $(config.scrollTarget).scroll(scrollHandler);
        scrollHandler();
    }

    // counter begin
    function Counter(container, count, options) {

        var defaults = {
            init: true,
            count: count,
            print: null,
            complete: null,
            timespan: 1000,
            decrement: 1,
            toFixed: 0
        };
        var settings = $.extend(defaults, options);

        var $container = $(container),
            clearId,
            status = 0;

        function init() {
            count = defaults.count;
            print();
        }

        function print() {
            var printText = settings.print ? settings.print(count) : count;
            $container.text(printText);
        }

        function decrement() {
            count = (count - settings.decrement).toFixed(settings.toFixed);
        }

        function start() {
            if (status == 1 || count <= 0) return;
            status = 1;
            clearTimeout(clearId);
            clearId = setInterval(function () {
                decrement();
                print();
                if (count <= 0) {
                    settings.complete && settings.complete.call($container);
                    clearInterval(clearId);
                }
            }, settings.timespan);
        }

        function pause() {
            status = 0;
            clearInterval(clearId);
        }

        function reset() {
            count = defaults.count;
            pause();
            init();
        }

        settings.init && init();

        return {
            start: start,
            pause: pause,
            reset: reset
        }
    }
    // counter end

    // timer begin
    function Timer(container, time, options) {
        var defaults = {
            format: "HH:mm:ss",
            tick: null,
            print: function (second) {
                this.tick && this.tick(second);
                return secondToTimeString(second, this.format);
            }
        };
        var config = $.extend(defaults, options);
        var timer = new Counter(container, timeStringToSecond(time), config);
        return timer;
    }

    function timeStringToSecond(formatted) {
        var arr = formatted.split(":").reverse();
        var second = 0;
        for (var i = 0; i < arr.length; i++) {
            second += parseInt(arr[i]) * Math.pow(60, i);
        }
        return second;
    }

    function secondToTimeString(second, formatted) {
        if (!formatted) formatted = "HH:mm:ss";
        var hour = 0, minute = 0;
        if (second >= 3600 && /HH/.test(formatted)) {
            hour = Math.floor(second / 3600);
            second = second % 3600;
        }
        if (second >= 60 && /mm/.test(formatted)) {
            minute = Math.floor(second / 60);
            second = second % 60;
        }
        return formatted.replace("HH", padLeftString(hour, 0, 2))
                         .replace("mm", padLeftString(minute, 0, 2))
                         .replace("ss", padLeftString(second, 0, 2));
    }
    // timer end
    
    return {
        BindButtons: bindButtons,
        Message: message,
        ExtendModal: extendModal,
        PadLeftStr: padLeftStr,
        PadLeftString: padLeftString,
        PadRightStr: padRightStr,
        PadRightString: padRightString,
        BackToTop: backToTop,
        Counter: Counter,
        Timer: Timer,
        TimeStringToSecond: timeStringToSecond,
        SecondToTimeString: secondToTimeString
    }

})();

//原生js扩展
(function () {

    String.prototype.toInt = function(){
        return parseInt(this.match(/\d+/));
    };

    String.prototype.toFloat = function(){
        return parseFloat(this.match(/\d+.\d+/));
    };

    String.prototype.padLeft = function (char, length) {
        return Global.PadLeftString(this, char, length);
    };

    String.prototype.padRight = function (char, length) {
        return Global.PadRightString(this, char, length);
    };

    Array.prototype.forEach = function(callback){
        for (var i=0; i<this.length; i++){
            callback && callback.call(this[i], this[i], i, this)
        }
    };

    (function () {
        Date.prototype.format = function (formatter) {
            var _this = this,
                year = _this.getFullYear().toString(),
                month = (_this.getMonth() + 1).toString(),
                day = _this.getDate().toString(),
                hour = _this.getHours().toString(),
                minute = _this.getMinutes().toString(),
                second = _this.getSeconds().toString();

            var formatted = formatter.replace(/y+/g, function (match) {
                return year.substring(year.length, year.length - match.length);
            }).replace(/M+/g, function (match) {
                return process(month, match, match.length);
            }).replace(/d+/g, function (match) {
                return process(day, match, match.length);
            }).replace(/H+/g, function (match) {
                return process(hour, match, 2);
            }).replace(/m+/g, function (match) {
                return process(minute, match, 2);
            }).replace(/s+/g, function (match) {
                return process(second, match, 2);
            });

            return formatted;
        };

        Date.prototype.addDay = function(number){
            this.setDate(this.getDate() + number);
            return this;
        }

        function process(data, match, length) {
            if (!length) length = 0;
            var end = data.length > 1 ? 0 : data.length - match.length;
            return data.substring(data.length, end).padLeft("0", length);
        }
    })();

})();

//jQuery方法扩展
(function () {

    jQuery.fn.BackToTop = function (options) {
        Global.BackToTop(this, options);
    }

})();

$(function () {
    Global.BindButtons();
    Global.ExtendModal();
});